//
//  Printer.m
//  pa
//
//  Created by HaiJiao Chen on 12-12-24.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "Printer.h"
#import "StarIO/SMPort.h"
#import "AppDelegate.h"
#import "MiniPrinterFunctions.h"
#import "KXActionSheet.h"
#import "PrinterSelect.h"
#include <sys/time.h>

@implementation Printer

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [self connect];
    [textField resignFirstResponder];
    return YES;
}

- (void)viewLoadFromNib:(NSNumber*)param
{
    [AppDelegate setPortSettings:@"mini"];
    NSMutableArray* temp = [[NSMutableArray alloc] initWithCapacity:10];
    for (PortInfo* portInfo in [SMPort searchPrinter])
    {
        [temp addObject:portInfo.portName];
    }
    portNameInfo.printers = temp;
    if ([temp count] > 0)
    {
        [portNameInfo setPrinter:[temp objectAtIndex:0]];
    }
    [temp release];
    [self connect];
}

- (void)clean
{
    enableCheckLoop = NO;
    
    if (queue != nil) {
        dispatch_release(queue);
    }
    
    if (starPort != nil) {
        [SMPort releasePort:starPort];
        [starPort release];
    }
}
- (void)connect
{
    [self clean];
    
    NSString *portName = [portNameInfo selectPrinter];
    NSString *portSettings = [AppDelegate getPortSettings];
        
    if ([[portName uppercaseString] hasPrefix:@"BT:"] == NO) {
        message.text = @"This function is supported only on Bluetooth I/F.";
        return;
    }
    
    starPort = [[SMPort alloc] init:portName :portSettings :10000];
    if (starPort == nil) {
        enableCheckLoop = NO;
        
        statusInfo.text = @"NO";
        message.text = @"Please do pairing with the printer again and tap connect button.";
        
        connectButton.hidden = NO;
        sampleReceiptButton.hidden = YES;
        getStatusButton.hidden = YES;
    } else {
        
        enableCheckLoop = YES;
        
        queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
            BOOL connected = NO;
            
            while (enableCheckLoop) {
                if (connected != starPort.connected) {
                    connected = starPort.connected;
                    
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (connected == YES) {
                            statusInfo.text = @"YES";
                            message.text = @"";
                            
                            connectButton.hidden = YES;
                            sampleReceiptButton.hidden = NO;
                            getStatusButton.hidden = NO;
                        }
                        else {
                            enableCheckLoop = NO;
                            
                            statusInfo.text = @"NO";
                            message.text = @"Please do pairing with the printer again and tap connect button.";
                            
                            connectButton.hidden = NO;
                            sampleReceiptButton.hidden = YES;
                            getStatusButton.hidden = YES;
                            
                            if (starPort != nil) {
                                [SMPort releasePort:starPort];
                                starPort = nil;
                            }
                        }
                    });
                }
                
                usleep(5000 * 1000); //Interval : 5sec
            }
            
            if (queue != nil) {
                dispatch_release(queue);
                queue = nil;
            }
        });
    }
}

- (IBAction)printTextFormating
{
    [AppDelegate setPortName:[portNameInfo selectPrinter]];
    NSString *portName = [AppDelegate getPortName];
    NSString *portSettings = [AppDelegate getPortSettings];
    
    bool underline = NO;
    bool emphasized = NO;
    bool upsidedown = NO;
    bool inverColor = NO;
    
    unsigned char heightExpansion = 0;
    unsigned char widthExpansion = 0;
    int leftMargin = 0;
    
    Alignment alignment = 0;
    NSData *textData = [@"this is test print\nhahaha\na lot of shit" dataUsingEncoding:NSWindowsCP1252StringEncoding];
    
    unsigned char *textBytes = (unsigned char*)malloc([textData length]);
    [textData getBytes:textBytes];
    
    [MiniPrinterFunctions PrintText:portName 
                       PortSettings:portSettings 
                          Underline:underline 
                         Emphasized:emphasized
                        Upsideddown:upsidedown
                        InvertColor:inverColor
                    HeightExpansion:heightExpansion
                     WidthExpansion:widthExpansion
                         LeftMargin:leftMargin
                          Alignment:alignment
                        TextToPrint:textBytes
                    TextToPrintSize:[textData length]];
    
    free(textBytes);
}


- (IBAction)pushButtonSampleReceipt:(id)sender
{
    KXActionSheet* action = [[KXActionSheet alloc] init];
    [action addButtonWithTitle:@"2 inch" code:^(id p1, id p2, id p3) {
        [self printSampleReceipt2inch];
    } param:nil];
    [action addButtonWithTitle:@"3 inch" code:^(id p1, id p2, id p3) {
        [self printSampleReceipt3inch];
    } param:nil];
    [action addButtonWithTitle:@"Cancel" code:nil param:nil];
    [action setTitle:@"Paper Width"];
    [action setCancelButtonIndex:2];
    [action showInView:self];
    [action release];
}


- (void)printSampleReceipt2inch
{
    NSData *commands = [MiniPrinterFunctions create2InchReceipt];
    
    unsigned char *commandsToSendToPrinter = (unsigned char*)malloc([commands length]);
    [commands getBytes:commandsToSendToPrinter];
    int commandSize = [commands length];
    
    @try
    {
        struct timeval endTime;
        gettimeofday(&endTime, NULL);
        endTime.tv_sec += 30;
        
        int totalAmountWritten = 0;
        while (totalAmountWritten < commandSize)
        {
            int remaining = commandSize - totalAmountWritten;
            
            int blockSize = (remaining > 1024) ? 1024 : remaining;
            
            int amountWritten = [starPort writePort:commandsToSendToPrinter :totalAmountWritten :blockSize];
            totalAmountWritten += amountWritten;
            
            struct timeval now;
            gettimeofday(&now, NULL);
            if (now.tv_sec > endTime.tv_sec)
            {
                break;
            }
        }
        
        if (totalAmountWritten < commandSize)
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Printer Error"
                                                            message:@"Write port timed out"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
            [alert release];
        }
    }
    @catch (PortException *exception)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Printer Error"
                                                        message:@"Write port timed out"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    
    free(commandsToSendToPrinter);
    [commands release];
}

- (void)printSampleReceipt3inch
{
    NSData *commands = [MiniPrinterFunctions create3InchReceipt];
    
    unsigned char *commandsToSendToPrinter = (unsigned char*)malloc([commands length]);
    [commands getBytes:commandsToSendToPrinter];
    int commandSize = [commands length];
    
    @try
    {
        struct timeval endTime;
        gettimeofday(&endTime, NULL);
        endTime.tv_sec += 30;
        
        int totalAmountWritten = 0;
        while (totalAmountWritten < commandSize)
        {
            int remaining = commandSize - totalAmountWritten;
            
            int blockSize = (remaining > 1024) ? 1024 : remaining;
            
            int amountWritten = [starPort writePort:commandsToSendToPrinter :totalAmountWritten :blockSize];
            totalAmountWritten += amountWritten;
            
            struct timeval now;
            gettimeofday(&now, NULL);
            if (now.tv_sec > endTime.tv_sec)
            {
                break;
            }
        }
        
        if (totalAmountWritten < commandSize)
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Printer Error"
                                                            message:@"Write port timed out"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
            [alert release];
        }
    }
    @catch (PortException *exception)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Printer Error"
                                                        message:@"Write port timed out"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    
    free(commandsToSendToPrinter);
    [commands release];
}

- (IBAction)pushButtonGetStatus:(id)sender {
    @try {
        StarPrinterStatus_2 status;
        [starPort getParsedStatus:&status :2];
        
        NSString *statusMessage = @"";
        if (status.offline == SM_TRUE)
        {
            statusMessage = @"The printer is offline";
            if (status.coverOpen == SM_TRUE)
            {
                statusMessage = [statusMessage stringByAppendingString:@"\nCover is Open"];
            }
            else if (status.receiptPaperEmpty == SM_TRUE)
            {
                statusMessage = [statusMessage stringByAppendingString:@"\nOut of Paper"];
            }
        }
        else
        {
            statusMessage = @"The Printer is online";
        }
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Printer Status"
                                                        message:statusMessage
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
        return;
    }
    @catch (PortException *e)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Printer Error"
                                                        message:@"Get status failed"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
}

- (IBAction)pushButtonConnect:(id)sender {
    [self connect];
}

- (IBAction)pushButtonBack:(id)sender {
    [self clean];
    [self removeFromSuperview];
}

- (void)dealloc {
    [portNameInfo release];
    [statusInfo release];
    [message release];
    [getStatusButton release];
    [sampleReceiptButton release];
    [connectButton release];
    [super dealloc];
}
@end
